#include <algorithm>
#include <climits>
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>

/**
 * Luogu P1396: Rescue
 * This problem can be solved either by Shortest Path or Minimal Spanning Tree.
 */

struct Edge {
    int to;
    int crowd;

    Edge(int to, int crowd) : to(to), crowd(crowd) {}
};

struct Vertex {
    int index;
    std::vector<Edge> edges;
    int crowd;

    Vertex(int idx) : index(idx), crowd(INT_MAX) {}
};

struct Cmp {
    bool operator()(Vertex *a, Vertex *b) const { return a->crowd > b->crowd; }
};

std::vector<Vertex> vertices;

int main() {
    // Input
    int nVerts, nEdges, begin, end;
    scanf("%d %d %d %d", &nVerts, &nEdges, &begin, &end);
    begin--, end--;
    for (int i = 0; i < nVerts; i++) vertices.emplace_back(i);
    for (int i = 0; i < nEdges; i++) {
        int from, to, crowd;
        scanf("%d %d %d", &from, &to, &crowd);
        from--, to--;
        vertices[from].edges.emplace_back(to, crowd);
        vertices[to].edges.emplace_back(from, crowd);
    }

    // Use Dijkstra algorithm to find least crowded path
    std::priority_queue<Vertex *, std::vector<Vertex *>, Cmp> heap;
    vertices[begin].crowd = 0;
    heap.push(&vertices[begin]);
    while (!heap.empty()) {
        Vertex *u = heap.top();
        heap.pop();
        for (auto &edge : u->edges) {
            Vertex *v = &vertices[edge.to];
            int newCrowd = std::max(u->crowd, edge.crowd);
            if (newCrowd < v->crowd) {
                v->crowd = newCrowd;
                heap.push(v);
            }
        }
    }
    printf("%d\n", vertices[end].crowd);

    return 0;
}